﻿using Microsoft.Xaml.Behaviors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace SimpleWpfTemplate
{
	#region << 版 本 注 释 >>
	/*----------------------------------------------------------------
	 * 版权所有 (c) 2025   保留所有权利。
	 * CLR版本：4.0.30319.42000
	 * 公司名称：
	 * 命名空间：SimpleWpfTemplate
	 * 唯一标识：d6502df3-9409-4634-9abc-3f23a3382253
	 * 文件名：AutoScrollBehavior
	 * 
	 * 创建者：dongming
	 * 电子邮箱：15688277399@163.com
	 * 创建时间：2025/6/16 13:46:56
	 * 版本：V1.0.0
	 * 描述：
	 *----------------------------------------------------------------*/
	#endregion << 版 本 注 释 >>
	public class AutoScrollBehavior: Behavior<RichTextBox>
	{
		private bool _autoScroll = true;

		protected override void OnAttached()
		{
			base.OnAttached();
			AssociatedObject.Loaded += RichTextBoxLoaded;
			AssociatedObject.TextChanged += RichTextBoxTextChanged;
		}

		protected override void OnDetaching()
		{
			AssociatedObject.Loaded -= RichTextBoxLoaded;
			AssociatedObject.TextChanged -= RichTextBoxTextChanged;
			base.OnDetaching();
		}

		private void RichTextBoxLoaded(object sender, RoutedEventArgs e)
		{
			var scrollViewer = GetScrollViewer(AssociatedObject);
			if (scrollViewer != null)
			{
				scrollViewer.ScrollChanged += ScrollViewerScrollChanged;
			}
		}

		private void RichTextBoxTextChanged(object sender, TextChangedEventArgs e)
		{
			if (_autoScroll)
			{
				ScrollToBottom();
			}
		}

		private void ScrollViewerScrollChanged(object sender, ScrollChangedEventArgs e)
		{
			// 用户手动滚动时暂停自动滚动
			if (e.VerticalChange > 0 && Math.Abs(e.VerticalOffset - e.ExtentHeight + e.ViewportHeight) < 1.0)
			{
				_autoScroll = true; // 滚动到底部时恢复自动滚动
			}
			else
			{
				_autoScroll = false; // 用户向上滚动时暂停自动滚动
			}
		}

		private void ScrollToBottom()
		{
			AssociatedObject.ScrollToEnd();
		}

		private static ScrollViewer GetScrollViewer(DependencyObject depObj)
		{
			if (depObj is ScrollViewer scrollViewer)
				return scrollViewer;

			for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
			{
				var child = VisualTreeHelper.GetChild(depObj, i);
				var result = GetScrollViewer(child);
				if (result != null)
					return result;
			}
			return null;
		}
	}
}
